#include "NodeEditor.h"
namespace Editor 
{
	ImU32 ColorNodeEditor::evaluate(const Graph<Node>& graph, const int root_node)
	{
		std::stack<int> postorder;
		dfs_traverse(
			graph, root_node, [&postorder](const int node_id) -> void { postorder.push(node_id); });

		std::stack<float> value_stack;
		while (!postorder.empty())
		{
			const int id = postorder.top();
			postorder.pop();
			const Node node = graph.node(id);

			switch (node.type)
			{
			case NodeType::add:
			{
				const float rhs = value_stack.top();
				value_stack.pop();
				const float lhs = value_stack.top();
				value_stack.pop();
				value_stack.push(lhs + rhs);
			}
			break;
			case NodeType::multiply:
			{
				const float rhs = value_stack.top();
				value_stack.pop();
				const float lhs = value_stack.top();
				value_stack.pop();
				value_stack.push(rhs * lhs);
			}
			break;
			case NodeType::sine:
			{
				const float x = value_stack.top();
				value_stack.pop();
				const float res = std::abs(std::sin(x));
				value_stack.push(res);
			}
			break;
			case NodeType::time:
			{
				value_stack.push(this->current_time_seconds);
			}
			break;
			case NodeType::value:
			{
				// If the edge does not have an edge connecting to another node, then just use the value
				// at this node. It means the node's input pin has not been connected to anything and
				// the value comes from the node's UI.
				if (graph.num_edges_from_node(id) == 0ull)
				{
					value_stack.push(node.value);
				}
			}
			break;
			default:
				break;
			}
		}

		// The final output node isn't evaluated in the loop -- instead we just pop
		// the three values which should be in the stack.
		assert(value_stack.size() == 3ull);
		const int b = static_cast<int>(255.f * std::clamp(value_stack.top(), 0.f, 1.f) + 0.5f);
		value_stack.pop();
		const int g = static_cast<int>(255.f * std::clamp(value_stack.top(), 0.f, 1.f) + 0.5f);
		value_stack.pop();
		const int r = static_cast<int>(255.f * std::clamp(value_stack.top(), 0.f, 1.f) + 0.5f);
		value_stack.pop();

		return IM_COL32(r, g, b, 255);
	}
}